<!-- @format -->

<template>
  <div class="editor-container">
    <!-- 左侧组件区域 -->
    <div class="left-panel">
      <h3>组件</h3>
      <div class="component-list">
        <button class="component-item" @click="addText">添加文本</button>
        <button class="component-item" @click="addImage">添加图片</button>
        <button class="component-item" @click="addRectangle">添加矩形</button>
        <button class="component-item" @click="addCircle">添加圆形</button>
        <button class="component-item export-btn" @click="exportData">
          导出数据
        </button>
        <button class="component-item import-btn" @click="importData">
          导入数据
        </button>
        <input
          type="file"
          ref="fileInput"
          style="display: none"
          @change="handleFileChange"
          accept=".json"
        />
      </div>
    </div>

    <!-- 中间Canvas展示区域 -->
    <div class="center-panel">
      <canvas
        ref="canvas"
        width="800"
        height="600"
        @mousedown="handleMouseDown"
        @mousemove="handleMouseMove"
        @mouseup="handleMouseUp"
      ></canvas>
    </div>

    <!-- 右侧属性设置区域 -->
    <div class="right-panel">
      <h3>属性设置</h3>
      <div v-if="selectedElementIndex !== -1" class="property-panel">
        <!-- 通用属性：位置 -->
        <div class="property-item">
          <label>X 位置:</label>
          <input v-model="x" type="number" placeholder="X 位置" />
        </div>

        <div class="property-item">
          <label>Y 位置:</label>
          <input v-model="y" type="number" placeholder="Y 位置" />
        </div>

        <!-- 文本元素特有属性 -->
        <template v-if="elementType === 'text'">
          <div class="property-item">
            <label>文本内容:</label>
            <input v-model="text" placeholder="输入文字" />
          </div>

          <div class="property-item">
            <label>字体:</label>
            <select v-model="fontFamily">
              <option value="Arial">Arial</option>
              <option value="Helvetica">Helvetica</option>
              <option value="Times New Roman">Times New Roman</option>
            </select>
          </div>

          <div class="property-item">
            <label>字号:</label>
            <input v-model="fontSize" type="number" placeholder="字号" />
          </div>

          <div class="property-status">文字已选中</div>
        </template>

        <!-- 图片元素特有属性 -->
        <template v-else-if="elementType === 'image'">
          <div class="property-item">
            <label>图片地址:</label>
            <input v-model="imageUrl" placeholder="输入图片URL" />
          </div>

          <div class="property-item">
            <label>宽度:</label>
            <input v-model="width" type="number" placeholder="宽度" />
          </div>

          <div class="property-item">
            <label>高度:</label>
            <input v-model="height" type="number" placeholder="高度" />
          </div>

          <div class="property-status">图片已选中</div>
        </template>

        <!-- 矩形元素特有属性 -->
        <template v-else-if="elementType === 'rectangle'">
          <div class="property-item">
            <label>宽度:</label>
            <input v-model="width" type="number" placeholder="宽度" />
          </div>

          <div class="property-item">
            <label>高度:</label>
            <input v-model="height" type="number" placeholder="高度" />
          </div>

          <div class="property-item">
            <label>颜色:</label>
            <input v-model="color" type="color" />
          </div>

          <div class="property-status">矩形已选中</div>
        </template>

        <!-- 圆形元素特有属性 -->
        <template v-else-if="elementType === 'circle'">
          <div class="property-item">
            <label>半径:</label>
            <input v-model="radius" type="number" placeholder="半径" />
          </div>

          <div class="property-item">
            <label>颜色:</label>
            <input v-model="color" type="color" />
          </div>

          <div class="property-status">圆形已选中</div>
        </template>
      </div>
      <div v-else class="no-selection">请在画布中选择一个元素</div>
    </div>
  </div>
</template>

<script setup>
  import { ref, onMounted, watch } from 'vue'

  // 定义画布引用
  const canvas = ref(null)
  const fileInput = ref(null)
  // 定义元素类型枚举
  const ElementType = {
    TEXT: 'text',
    IMAGE: 'image',
    RECTANGLE: 'rectangle',
    CIRCLE: 'circle',
  }

  // 定义控制点位置枚举
  const ControlPointPosition = {
    TOP_LEFT: 'top-left',
    TOP_CENTER: 'top-center',
    TOP_RIGHT: 'top-right',
    MIDDLE_LEFT: 'middle-left',
    MIDDLE_RIGHT: 'middle-right',
    BOTTOM_LEFT: 'bottom-left',
    BOTTOM_CENTER: 'bottom-center',
    BOTTOM_RIGHT: 'bottom-right',
  }

  // 定义画布元素数组
  const canvasElements = ref([
    {
      id: 1,
      type: ElementType.TEXT,
      text: 'Hello, World!',
      fontFamily: 'Arial',
      fontSize: 30,
      x: 100,
      y: 100,
      isSelected: false,
    },
  ])
  // 当前选中的元素索引
  const selectedElementIndex = ref(-1)
  // 当前编辑的元素属性（用于右侧面板）
  const elementType = ref(ElementType.TEXT)
  const text = ref('Hello, World!')
  const fontFamily = ref('Arial')
  const fontSize = ref(30)
  const x = ref(100)
  const y = ref(100)
  const width = ref(100)
  const height = ref(100)
  const radius = ref(50)
  const color = ref('#000000')
  const imageUrl = ref('')
  // 鼠标是否悬停在元素上
  const isOverElement = ref(false)
  // 拖拽状态
  const isDragging = ref(false)
  // 拖拽起始位置
  const dragStartX = ref(0)
  const dragStartY = ref(0)
  // 底图对象
  const image = new Image()
  // 控制点相关状态
  const activeControlPoint = ref(null) // 当前激活的控制点
  const isResizing = ref(false) // 是否正在调整大小
  const controlPointSize = 8 // 控制点大小
  const controlPointColor = '#1890ff' // 控制点颜色

  // 添加文本的方法
  const addText = () => {
    // 创建新的文本元素
    const newX = Math.floor(Math.random() * 400) + 100
    const newY = Math.floor(Math.random() * 300) + 100
    const newId =
      canvasElements.value.length > 0
        ? Math.max(...canvasElements.value.map((el) => el.id)) + 1
        : 1

    // 取消之前选中的元素
    if (selectedElementIndex.value !== -1) {
      canvasElements.value[selectedElementIndex.value].isSelected = false
    }

    // 添加新文本元素
    const newElement = {
      id: newId,
      type: ElementType.TEXT,
      text: '新文本',
      fontFamily: 'Arial',
      fontSize: 30,
      x: newX,
      y: newY,
      isSelected: true,
    }
    canvasElements.value.push(newElement)

    // 更新选中索引和编辑面板数据
    selectedElementIndex.value = canvasElements.value.length - 1
    updateEditingProperties()

    // 重新绘制
    const ctx = canvas.value.getContext('2d')
    drawCanvas(ctx)
  }

  // 添加图片的方法
  const addImage = () => {
    // 创建新的图片元素
    const newX = Math.floor(Math.random() * 400) + 100
    const newY = Math.floor(Math.random() * 300) + 100
    const newId =
      canvasElements.value.length > 0
        ? Math.max(...canvasElements.value.map((el) => el.id)) + 1
        : 1

    // 取消之前选中的元素
    if (selectedElementIndex.value !== -1) {
      canvasElements.value[selectedElementIndex.value].isSelected = false
    }

    // 添加新图片元素
    const newElement = {
      id: newId,
      type: ElementType.IMAGE,
      x: newX,
      y: newY,
      width: 200,
      height: 150,
      imageUrl: '/public/vite.svg', // 默认使用项目中的图片
      isSelected: true,
    }
    canvasElements.value.push(newElement)

    // 更新选中索引和编辑面板数据
    selectedElementIndex.value = canvasElements.value.length - 1
    updateEditingProperties()

    // 重新绘制
    const ctx = canvas.value.getContext('2d')
    drawCanvas(ctx)
  }

  // 添加矩形的方法
  const addRectangle = () => {
    // 创建新的矩形元素
    const newX = Math.floor(Math.random() * 400) + 100
    const newY = Math.floor(Math.random() * 300) + 100
    const newId =
      canvasElements.value.length > 0
        ? Math.max(...canvasElements.value.map((el) => el.id)) + 1
        : 1

    // 取消之前选中的元素
    if (selectedElementIndex.value !== -1) {
      canvasElements.value[selectedElementIndex.value].isSelected = false
    }

    // 添加新矩形元素
    const newElement = {
      id: newId,
      type: ElementType.RECTANGLE,
      x: newX,
      y: newY,
      width: 150,
      height: 100,
      color: '#3498db',
      isSelected: true,
    }
    canvasElements.value.push(newElement)

    // 更新选中索引和编辑面板数据
    selectedElementIndex.value = canvasElements.value.length - 1
    updateEditingProperties()

    // 重新绘制
    const ctx = canvas.value.getContext('2d')
    drawCanvas(ctx)
  }

  // 添加圆形的方法
  const addCircle = () => {
    // 创建新的圆形元素
    const newX = Math.floor(Math.random() * 400) + 100
    const newY = Math.floor(Math.random() * 300) + 100
    const newId =
      canvasElements.value.length > 0
        ? Math.max(...canvasElements.value.map((el) => el.id)) + 1
        : 1

    // 取消之前选中的元素
    if (selectedElementIndex.value !== -1) {
      canvasElements.value[selectedElementIndex.value].isSelected = false
    }

    // 添加新圆形元素
    const newElement = {
      id: newId,
      type: ElementType.CIRCLE,
      x: newX,
      y: newY,
      radius: 50,
      color: '#e74c3c',
      isSelected: true,
    }
    canvasElements.value.push(newElement)

    // 更新选中索引和编辑面板数据
    selectedElementIndex.value = canvasElements.value.length - 1
    updateEditingProperties()

    // 重新绘制
    const ctx = canvas.value.getContext('2d')
    drawCanvas(ctx)
  }

  // 导出数据的方法
  const exportData = async () => {
    try {
      // 创建要导出的数据对象
      const exportData = {
        canvasSize: {
          width: canvas.value.width,
          height: canvas.value.height,
        },
        backgroundImage: image.src, // 保存底图URL
        elements: canvasElements.value.map((element) => {
          // 创建基本元素数据
          const baseData = {
            id: element.id,
            type: element.type,
            x: element.x,
            y: element.y,
            isSelected: false, // 重置选中状态
          }

          // 根据元素类型添加特定属性
          switch (element.type) {
            case ElementType.TEXT:
              return {
                ...baseData,
                text: element.text,
                fontFamily: element.fontFamily,
                fontSize: element.fontSize,
              }
            case ElementType.IMAGE:
              return {
                ...baseData,
                width: element.width,
                height: element.height,
                imageUrl: element.imageUrl,
              }
            case ElementType.RECTANGLE:
              return {
                ...baseData,
                width: element.width,
                height: element.height,
                color: element.color,
              }
            case ElementType.CIRCLE:
              return {
                ...baseData,
                radius: element.radius,
                color: element.color,
              }
            default:
              return baseData
          }
        }),
      }

      // 创建一个临时画布用于导出预览图
      const tempCanvas = document.createElement('canvas')
      tempCanvas.width = canvas.value.width
      tempCanvas.height = canvas.value.height
      const tempCtx = tempCanvas.getContext('2d')

      // 等待底图加载完成
      await new Promise((resolve, reject) => {
        const img = new Image()
        img.crossOrigin = 'anonymous'
        img.src = image.src
        img.onload = () => {
          tempCtx.drawImage(img, 0, 0, tempCanvas.width, tempCanvas.height)
          resolve()
        }
        img.onerror = reject
      })

      // 等待所有图片元素加载完成并绘制所有元素
      await Promise.all(
        canvasElements.value.map(async (element) => {
          if (element.type === ElementType.TEXT) {
            tempCtx.font = `${element.fontSize}px ${element.fontFamily}`
            tempCtx.fillStyle = 'black'
            tempCtx.fillText(element.text, element.x, element.y)
          } else if (element.type === ElementType.IMAGE) {
            await new Promise((resolve, reject) => {
              const img = new Image()
              img.crossOrigin = 'anonymous'
              img.src = element.imageUrl
              img.onload = () => {
                tempCtx.drawImage(
                  img,
                  element.x,
                  element.y,
                  element.width,
                  element.height,
                )
                resolve()
              }
              img.onerror = reject
            })
          } else if (element.type === ElementType.RECTANGLE) {
            tempCtx.fillStyle = element.color
            tempCtx.fillRect(
              element.x,
              element.y,
              element.width,
              element.height,
            )
          } else if (element.type === ElementType.CIRCLE) {
            tempCtx.fillStyle = element.color
            tempCtx.beginPath()
            tempCtx.arc(element.x, element.y, element.radius, 0, Math.PI * 2)
            tempCtx.fill()
          }
        }),
      )

      // 获取预览图的base64数据
      const previewImage = tempCanvas.toDataURL('image/png')

      // 清理临时画布
      tempCanvas.remove()

      console.log('Base64预览地址:', previewImage)

      // 创建包含完整数据的导出对象
      const fullExportData = {
        canvasData: exportData,
        previewImage: previewImage,
      }

      // 将数据转换为JSON字符串并下载
      const jsonStr = JSON.stringify(fullExportData, null, 2)
      const blob = new Blob([jsonStr], { type: 'application/json' })
      const url = URL.createObjectURL(blob)
      const a = document.createElement('a')
      a.href = url
      a.download = 'canvas_data.json'
      document.body.appendChild(a)
      a.click()
      document.body.removeChild(a)
      URL.revokeObjectURL(url)

      return fullExportData
    } catch (error) {
      console.error('导出数据失败:', error)
      alert(
        '导出失败，可能是由于画布中包含跨域资源，请确保所有图片资源允许跨域访问。',
      )
    }
  }

  // 导出base64的方法
  // 处理文件导入
  const handleFileChange = async (event) => {
    try {
      const file = event.target.files[0]
      if (!file) return

      const reader = new FileReader()
      reader.onload = async (e) => {
        try {
          const importedData = JSON.parse(e.target.result)
          console.log('导入的数据:', importedData)
          const { canvasData, previewImage } = importedData

          // 更新画布尺寸
          canvas.value.width = canvasData.canvasSize.width
          canvas.value.height = canvasData.canvasSize.height

          // 加载底图
          await new Promise((resolve, reject) => {
            image.src = canvasData.backgroundImage
            image.onload = resolve
            image.onerror = reject
          })

          // 更新元素数据
          canvasElements.value = canvasData.elements

          // 重新绘制画布
          const ctx = canvas.value.getContext('2d')
          drawCanvas(ctx)

          // 重置选中状态
          selectedElementIndex.value = -1
          updateEditingProperties()
        } catch (error) {
          console.error('解析导入数据失败:', error)
          alert('导入失败，请确保文件格式正确。')
        }
      }
      reader.readAsText(file)
    } catch (error) {
      console.error('读取文件失败:', error)
      alert('读取文件失败，请重试。')
    }
  }

  onMounted(() => {
    const ctx = canvas.value.getContext('2d')
    // 设置图片跨域属性
    image.crossOrigin = 'anonymous'
    // 加载底图
    image.src =
      'https://www4.bing.com//th?id=OHR.BlueNaxos_ZH-CN7863097040_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp' // 替换为实际的底图路径
    image.onload = () => {
      // 绘制底图
      ctx.drawImage(image, 0, 0, canvas.value.width, canvas.value.height)
      // 绘制所有元素
      drawCanvas(ctx)
    }
    image.onerror = (error) => {
      console.error('底图加载失败:', error)
    }
  })

  // 更新编辑面板属性
  const updateEditingProperties = () => {
    if (selectedElementIndex.value !== -1) {
      const selectedElement = canvasElements.value[selectedElementIndex.value]
      elementType.value = selectedElement.type
      x.value = selectedElement.x
      y.value = selectedElement.y

      // 根据元素类型设置特定属性
      if (selectedElement.type === ElementType.TEXT) {
        text.value = selectedElement.text
        fontFamily.value = selectedElement.fontFamily
        fontSize.value = selectedElement.fontSize
      } else if (selectedElement.type === ElementType.IMAGE) {
        width.value = selectedElement.width
        height.value = selectedElement.height
        imageUrl.value = selectedElement.imageUrl
      } else if (selectedElement.type === ElementType.RECTANGLE) {
        width.value = selectedElement.width
        height.value = selectedElement.height
        color.value = selectedElement.color
      } else if (selectedElement.type === ElementType.CIRCLE) {
        radius.value = selectedElement.radius
        color.value = selectedElement.color
      }
    }
  }

  // 将编辑面板的属性同步到选中的元素
  const syncPropertiesToSelectedElement = () => {
    if (selectedElementIndex.value !== -1) {
      const selectedElement = canvasElements.value[selectedElementIndex.value]
      selectedElement.x = x.value
      selectedElement.y = y.value

      // 根据元素类型同步特定属性
      if (selectedElement.type === ElementType.TEXT) {
        selectedElement.text = text.value
        selectedElement.fontFamily = fontFamily.value
        selectedElement.fontSize = fontSize.value
      } else if (selectedElement.type === ElementType.IMAGE) {
        selectedElement.width = width.value
        selectedElement.height = height.value
        selectedElement.imageUrl = imageUrl.value
      } else if (selectedElement.type === ElementType.RECTANGLE) {
        selectedElement.width = width.value
        selectedElement.height = height.value
        selectedElement.color = color.value
      } else if (selectedElement.type === ElementType.CIRCLE) {
        selectedElement.radius = radius.value
        selectedElement.color = color.value
      }
    }
  }

  const drawCanvas = (ctx) => {
    // 清除之前的内容
    ctx.clearRect(0, 0, canvas.value.width, canvas.value.height)
    // 绘制底图
    ctx.drawImage(image, 0, 0, canvas.value.width, canvas.value.height)

    // 绘制所有元素
    canvasElements.value.forEach((element) => {
      if (element.type === ElementType.TEXT) {
        drawTextElement(ctx, element)
      } else if (element.type === ElementType.IMAGE) {
        drawImageElement(ctx, element)
      } else if (element.type === ElementType.RECTANGLE) {
        drawRectangleElement(ctx, element)
      } else if (element.type === ElementType.CIRCLE) {
        drawCircleElement(ctx, element)
      }
    })
  }

  // 绘制文本元素
  const drawTextElement = (ctx, element) => {
    // 设置文字样式
    ctx.font = `${element.fontSize}px ${element.fontFamily}`
    // 根据选中状态设置文字颜色
    ctx.fillStyle = element.isSelected ? 'red' : 'black'
    // 绘制文字
    ctx.fillText(element.text, element.x, element.y)

    // 如果文字被选中，绘制边框
    if (element.isSelected) {
      // 获取文字宽度
      const textWidth = ctx.measureText(element.text).width
      // 绘制选中边框
      ctx.strokeStyle = 'blue'
      ctx.lineWidth = 2
      const x = element.x - 5
      const y = element.y - element.fontSize + 5
      const width = textWidth + 10
      const height = element.fontSize + 10
      ctx.strokeRect(x, y, width, height)

      // 绘制控制点
      drawControlPoints(ctx, x, y, width, height)
    }
  }

  // 绘制控制点的函数
  const drawControlPoints = (ctx, x, y, width, height) => {
    // 控制点位置
    const controlPoints = [
      { position: ControlPointPosition.TOP_LEFT, x: x, y: y },
      { position: ControlPointPosition.TOP_CENTER, x: x + width / 2, y: y },
      { position: ControlPointPosition.TOP_RIGHT, x: x + width, y: y },
      { position: ControlPointPosition.MIDDLE_LEFT, x: x, y: y + height / 2 },
      {
        position: ControlPointPosition.MIDDLE_RIGHT,
        x: x + width,
        y: y + height / 2,
      },
      { position: ControlPointPosition.BOTTOM_LEFT, x: x, y: y + height },
      {
        position: ControlPointPosition.BOTTOM_CENTER,
        x: x + width / 2,
        y: y + height,
      },
      {
        position: ControlPointPosition.BOTTOM_RIGHT,
        x: x + width,
        y: y + height,
      },
    ]

    // 绘制每个控制点
    controlPoints.forEach((point) => {
      ctx.fillStyle = controlPointColor
      ctx.fillRect(
        point.x - controlPointSize / 2,
        point.y - controlPointSize / 2,
        controlPointSize,
        controlPointSize,
      )
      ctx.strokeStyle = '#fff'
      ctx.lineWidth = 1
      ctx.strokeRect(
        point.x - controlPointSize / 2,
        point.y - controlPointSize / 2,
        controlPointSize,
        controlPointSize,
      )
    })
  }

  // 绘制图片元素
  const drawImageElement = (ctx, element) => {
    // 创建图片对象
    const img = new Image()
    img.crossOrigin = 'anonymous'
    img.src = element.imageUrl

    // 绘制图片
    try {
      ctx.drawImage(img, element.x, element.y, element.width, element.height)
    } catch (error) {
      // 如果图片加载失败，绘制占位符
      ctx.fillStyle = '#f1f1f1'
      ctx.fillRect(element.x, element.y, element.width, element.height)
      ctx.fillStyle = '#999'
      ctx.font = '14px Arial'
      ctx.fillText(
        '图片加载中...',
        element.x + 10,
        element.y + element.height / 2,
      )
    }

    // 如果图片被选中，绘制边框
    if (element.isSelected) {
      ctx.strokeStyle = 'blue'
      ctx.lineWidth = 2
      ctx.strokeRect(
        element.x - 2,
        element.y - 2,
        element.width + 4,
        element.height + 4,
      )

      // 绘制控制点
      drawControlPoints(
        ctx,
        element.x - 2,
        element.y - 2,
        element.width + 4,
        element.height + 4,
      )
    }
  }

  // 绘制矩形元素
  const drawRectangleElement = (ctx, element) => {
    // 设置填充颜色
    ctx.fillStyle = element.color
    // 绘制矩形
    ctx.fillRect(element.x, element.y, element.width, element.height)

    // 如果矩形被选中，绘制边框
    if (element.isSelected) {
      ctx.strokeStyle = 'blue'
      ctx.lineWidth = 2
      ctx.strokeRect(
        element.x - 2,
        element.y - 2,
        element.width + 4,
        element.height + 4,
      )

      // 绘制控制点
      drawControlPoints(
        ctx,
        element.x - 2,
        element.y - 2,
        element.width + 4,
        element.height + 4,
      )
    }
  }

  // 绘制圆形元素
  const drawCircleElement = (ctx, element) => {
    // 设置填充颜色
    ctx.fillStyle = element.color
    // 开始绘制路径
    ctx.beginPath()
    // 绘制圆形
    ctx.arc(element.x, element.y, element.radius, 0, Math.PI * 2)
    // 填充圆形
    ctx.fill()

    // 如果圆形被选中，绘制边框
    if (element.isSelected) {
      ctx.strokeStyle = 'blue'
      ctx.lineWidth = 2
      ctx.beginPath()
      ctx.arc(element.x, element.y, element.radius + 2, 0, Math.PI * 2)
      ctx.stroke()

      // 绘制控制点 - 为圆形创建一个虚拟的边界框
      const boundingX = element.x - element.radius - 2
      const boundingY = element.y - element.radius - 2
      const boundingWidth = (element.radius + 2) * 2
      const boundingHeight = (element.radius + 2) * 2
      drawControlPoints(
        ctx,
        boundingX,
        boundingY,
        boundingWidth,
        boundingHeight,
      )
    }
  }

  // 监听属性的变化，同步到选中元素并重新绘制
  watch(
    [text, fontFamily, fontSize, x, y, width, height, radius, color, imageUrl],
    () => {
      syncPropertiesToSelectedElement()
      const ctx = canvas.value.getContext('2d')
      drawCanvas(ctx)
    },
  )

  // 监听元素数组的变化，重新绘制
  watch(
    canvasElements,
    () => {
      const ctx = canvas.value.getContext('2d')
      drawCanvas(ctx)
    },
    { deep: true },
  )

  // 检查点击位置是否在指定元素区域内
  const isPointInElementArea = (element, mouseX, mouseY) => {
    if (element.type === ElementType.TEXT) {
      const ctx = canvas.value.getContext('2d')
      ctx.font = `${element.fontSize}px ${element.fontFamily}`
      const textWidth = ctx.measureText(element.text).width
      const textHeight = element.fontSize

      // 文字区域的边界
      const textLeft = element.x
      const textRight = element.x + textWidth
      const textTop = element.y - textHeight
      const textBottom = element.y

      // 检查点击位置是否在文字区域内
      return (
        mouseX >= textLeft &&
        mouseX <= textRight &&
        mouseY >= textTop &&
        mouseY <= textBottom
      )
    } else if (
      element.type === ElementType.IMAGE ||
      element.type === ElementType.RECTANGLE
    ) {
      // 矩形区域的边界
      const rectLeft = element.x
      const rectRight = element.x + element.width
      const rectTop = element.y
      const rectBottom = element.y + element.height

      // 检查点击位置是否在矩形区域内
      return (
        mouseX >= rectLeft &&
        mouseX <= rectRight &&
        mouseY >= rectTop &&
        mouseY <= rectBottom
      )
    } else if (element.type === ElementType.CIRCLE) {
      // 计算点击位置到圆心的距离
      const distance = Math.sqrt(
        Math.pow(mouseX - element.x, 2) + Math.pow(mouseY - element.y, 2),
      )

      // 检查点击位置是否在圆形区域内
      return distance <= element.radius
    }

    return false
  }

  // 检查点是否在控制点上
  const isPointInControlPoint = (
    mouseX,
    mouseY,
    controlPointX,
    controlPointY,
  ) => {
    const distance = Math.sqrt(
      Math.pow(mouseX - controlPointX, 2) + Math.pow(mouseY - controlPointY, 2),
    )
    return distance <= controlPointSize
  }

  // 获取元素的边界框
  const getElementBoundingBox = (element) => {
    if (element.type === ElementType.TEXT) {
      const ctx = canvas.value.getContext('2d')
      ctx.font = `${element.fontSize}px ${element.fontFamily}`
      const textWidth = ctx.measureText(element.text).width
      return {
        x: element.x - 5,
        y: element.y - element.fontSize + 5,
        width: textWidth + 10,
        height: element.fontSize + 10,
      }
    } else if (
      element.type === ElementType.IMAGE ||
      element.type === ElementType.RECTANGLE
    ) {
      return {
        x: element.x - 2,
        y: element.y - 2,
        width: element.width + 4,
        height: element.height + 4,
      }
    } else if (element.type === ElementType.CIRCLE) {
      return {
        x: element.x - element.radius - 2,
        y: element.y - element.radius - 2,
        width: (element.radius + 2) * 2,
        height: (element.radius + 2) * 2,
      }
    }
    return null
  }

  // 获取鼠标位置的控制点
  const getControlPointAtPosition = (mouseX, mouseY) => {
    if (selectedElementIndex.value === -1) return null

    const element = canvasElements.value[selectedElementIndex.value]
    const boundingBox = getElementBoundingBox(element)

    if (!boundingBox) return null

    const { x, y, width, height } = boundingBox

    // 控制点位置
    const controlPoints = [
      { position: ControlPointPosition.TOP_LEFT, x: x, y: y },
      { position: ControlPointPosition.TOP_CENTER, x: x + width / 2, y: y },
      { position: ControlPointPosition.TOP_RIGHT, x: x + width, y: y },
      { position: ControlPointPosition.MIDDLE_LEFT, x: x, y: y + height / 2 },
      {
        position: ControlPointPosition.MIDDLE_RIGHT,
        x: x + width,
        y: y + height / 2,
      },
      { position: ControlPointPosition.BOTTOM_LEFT, x: x, y: y + height },
      {
        position: ControlPointPosition.BOTTOM_CENTER,
        x: x + width / 2,
        y: y + height,
      },
      {
        position: ControlPointPosition.BOTTOM_RIGHT,
        x: x + width,
        y: y + height,
      },
    ]

    // 检查每个控制点
    for (const point of controlPoints) {
      if (isPointInControlPoint(mouseX, mouseY, point.x, point.y)) {
        return point.position
      }
    }

    return null
  }

  // 查找鼠标位置下的元素
  const findElementAtPosition = (mouseX, mouseY) => {
    // 从后向前检查（后添加的元素优先选中）
    for (let i = canvasElements.value.length - 1; i >= 0; i--) {
      if (isPointInElementArea(canvasElements.value[i], mouseX, mouseY)) {
        return i
      }
    }
    return -1
  }

  // 处理鼠标按下事件
  const handleMouseDown = (event) => {
    const rect = canvas.value.getBoundingClientRect()
    const mouseX = event.clientX - rect.left
    const mouseY = event.clientY - rect.top

    // 首先检查是否点击了控制点
    const controlPoint = getControlPointAtPosition(mouseX, mouseY)

    if (controlPoint && selectedElementIndex.value !== -1) {
      // 如果点击了控制点，进入调整大小模式
      isResizing.value = true
      activeControlPoint.value = controlPoint
      dragStartX.value = mouseX
      dragStartY.value = mouseY
    } else {
      // 否则按照原来的逻辑处理
      // 查找点击位置的元素
      const clickedIndex = findElementAtPosition(mouseX, mouseY)

      // 取消之前选中的元素
      if (selectedElementIndex.value !== -1) {
        canvasElements.value[selectedElementIndex.value].isSelected = false
      }

      // 更新选中状态
      if (clickedIndex !== -1) {
        canvasElements.value[clickedIndex].isSelected = true
        selectedElementIndex.value = clickedIndex
        updateEditingProperties()

        // 开始拖拽
        isDragging.value = true
        // 记录拖拽起始位置
        dragStartX.value = mouseX
        dragStartY.value = mouseY
      } else {
        selectedElementIndex.value = -1
      }
    }

    // 重新绘制
    const ctx = canvas.value.getContext('2d')
    drawCanvas(ctx)
  }

  // 处理鼠标移动事件
  const handleMouseMove = (event) => {
    const rect = canvas.value.getBoundingClientRect()
    const mouseX = event.clientX - rect.left
    const mouseY = event.clientY - rect.top

    // 如果正在调整大小
    if (
      isResizing.value &&
      selectedElementIndex.value !== -1 &&
      activeControlPoint.value
    ) {
      const selectedElement = canvasElements.value[selectedElementIndex.value]
      const deltaX = mouseX - dragStartX.value
      const deltaY = mouseY - dragStartY.value

      // 根据不同的控制点调整元素大小
      switch (activeControlPoint.value) {
        case ControlPointPosition.TOP_LEFT:
          if (selectedElement.type === ElementType.TEXT) {
            // 文本元素特殊处理
            selectedElement.x += deltaX
            selectedElement.y += deltaY
            selectedElement.fontSize = Math.max(
              10,
              selectedElement.fontSize - deltaY,
            )
          } else if (
            selectedElement.type === ElementType.RECTANGLE ||
            selectedElement.type === ElementType.IMAGE
          ) {
            selectedElement.x += deltaX
            selectedElement.y += deltaY
            selectedElement.width = Math.max(20, selectedElement.width - deltaX)
            selectedElement.height = Math.max(
              20,
              selectedElement.height - deltaY,
            )
          } else if (selectedElement.type === ElementType.CIRCLE) {
            const newRadius = Math.max(
              10,
              selectedElement.radius - Math.max(deltaX, deltaY) / 2,
            )
            selectedElement.radius = newRadius
          }
          break
        case ControlPointPosition.TOP_CENTER:
          if (selectedElement.type === ElementType.TEXT) {
            selectedElement.y += deltaY
            selectedElement.fontSize = Math.max(
              10,
              selectedElement.fontSize - deltaY,
            )
          } else if (
            selectedElement.type === ElementType.RECTANGLE ||
            selectedElement.type === ElementType.IMAGE
          ) {
            selectedElement.y += deltaY
            selectedElement.height = Math.max(
              20,
              selectedElement.height - deltaY,
            )
          } else if (selectedElement.type === ElementType.CIRCLE) {
            const newRadius = Math.max(10, selectedElement.radius - deltaY / 2)
            selectedElement.radius = newRadius
          }
          break
        case ControlPointPosition.TOP_RIGHT:
          if (selectedElement.type === ElementType.TEXT) {
            selectedElement.y += deltaY
            selectedElement.fontSize = Math.max(
              10,
              selectedElement.fontSize - deltaY,
            )
          } else if (
            selectedElement.type === ElementType.RECTANGLE ||
            selectedElement.type === ElementType.IMAGE
          ) {
            selectedElement.y += deltaY
            selectedElement.width = Math.max(20, selectedElement.width + deltaX)
            selectedElement.height = Math.max(
              20,
              selectedElement.height - deltaY,
            )
          } else if (selectedElement.type === ElementType.CIRCLE) {
            const newRadius = Math.max(
              10,
              selectedElement.radius - Math.min(deltaX, -deltaY) / 2,
            )
            selectedElement.radius = newRadius
          }
          break
        case ControlPointPosition.MIDDLE_LEFT:
          if (
            selectedElement.type === ElementType.RECTANGLE ||
            selectedElement.type === ElementType.IMAGE
          ) {
            selectedElement.x += deltaX
            selectedElement.width = Math.max(20, selectedElement.width - deltaX)
          } else if (selectedElement.type === ElementType.CIRCLE) {
            const newRadius = Math.max(10, selectedElement.radius - deltaX / 2)
            selectedElement.radius = newRadius
          }
          break
        case ControlPointPosition.MIDDLE_RIGHT:
          if (
            selectedElement.type === ElementType.RECTANGLE ||
            selectedElement.type === ElementType.IMAGE
          ) {
            selectedElement.width = Math.max(20, selectedElement.width + deltaX)
          } else if (selectedElement.type === ElementType.CIRCLE) {
            const newRadius = Math.max(10, selectedElement.radius + deltaX / 2)
            selectedElement.radius = newRadius
          }
          break
        case ControlPointPosition.BOTTOM_LEFT:
          if (
            selectedElement.type === ElementType.RECTANGLE ||
            selectedElement.type === ElementType.IMAGE
          ) {
            selectedElement.x += deltaX
            selectedElement.width = Math.max(20, selectedElement.width - deltaX)
            selectedElement.height = Math.max(
              20,
              selectedElement.height + deltaY,
            )
          } else if (selectedElement.type === ElementType.CIRCLE) {
            const newRadius = Math.max(
              10,
              selectedElement.radius - Math.min(-deltaY, deltaX) / 2,
            )
            selectedElement.radius = newRadius
          }
          break
        case ControlPointPosition.BOTTOM_CENTER:
          if (
            selectedElement.type === ElementType.RECTANGLE ||
            selectedElement.type === ElementType.IMAGE
          ) {
            selectedElement.height = Math.max(
              20,
              selectedElement.height + deltaY,
            )
          } else if (selectedElement.type === ElementType.CIRCLE) {
            const newRadius = Math.max(10, selectedElement.radius + deltaY / 2)
            selectedElement.radius = newRadius
          }
          break
        case ControlPointPosition.BOTTOM_RIGHT:
          if (
            selectedElement.type === ElementType.RECTANGLE ||
            selectedElement.type === ElementType.IMAGE
          ) {
            selectedElement.width = Math.max(20, selectedElement.width + deltaX)
            selectedElement.height = Math.max(
              20,
              selectedElement.height + deltaY,
            )
          } else if (selectedElement.type === ElementType.CIRCLE) {
            const newRadius = Math.max(
              10,
              selectedElement.radius + Math.max(deltaX, deltaY) / 2,
            )
            selectedElement.radius = newRadius
          }
          break
      }

      // 更新编辑面板中的值
      updateEditingProperties()

      // 更新拖拽起始位置为当前位置
      dragStartX.value = mouseX
      dragStartY.value = mouseY

      // 重新绘制
      const ctx = canvas.value.getContext('2d')
      drawCanvas(ctx)
    }
    // 如果正在拖拽且有选中的元素
    else if (isDragging.value && selectedElementIndex.value !== -1) {
      // 计算鼠标移动的距离
      const deltaX = mouseX - dragStartX.value
      const deltaY = mouseY - dragStartY.value

      // 更新元素的位置
      const selectedElement = canvasElements.value[selectedElementIndex.value]
      selectedElement.x += deltaX
      selectedElement.y += deltaY

      // 更新编辑面板中的位置值
      x.value = selectedElement.x
      y.value = selectedElement.y

      // 更新拖拽起始位置为当前位置
      dragStartX.value = mouseX
      dragStartY.value = mouseY

      // 重新绘制
      const ctx = canvas.value.getContext('2d')
      drawCanvas(ctx)
    } else {
      // 检查鼠标是否悬停在控制点上
      const controlPoint = getControlPointAtPosition(mouseX, mouseY)

      if (controlPoint) {
        // 根据控制点位置设置鼠标样式
        switch (controlPoint) {
          case ControlPointPosition.TOP_LEFT:
          case ControlPointPosition.BOTTOM_RIGHT:
            canvas.value.style.cursor = 'nwse-resize'
            break
          case ControlPointPosition.TOP_RIGHT:
          case ControlPointPosition.BOTTOM_LEFT:
            canvas.value.style.cursor = 'nesw-resize'
            break
          case ControlPointPosition.TOP_CENTER:
          case ControlPointPosition.BOTTOM_CENTER:
            canvas.value.style.cursor = 'ns-resize'
            break
          case ControlPointPosition.MIDDLE_LEFT:
          case ControlPointPosition.MIDDLE_RIGHT:
            canvas.value.style.cursor = 'ew-resize'
            break
        }
      } else {
        // 检查鼠标是否悬停在任何元素上
        const hoverIndex = findElementAtPosition(mouseX, mouseY)
        isOverElement.value = hoverIndex !== -1

        // 如果不在控制点上，恢复默认鼠标样式或移动样式
        canvas.value.style.cursor = isOverElement.value ? 'move' : 'default'
      }
    }
  }

  // 处理鼠标松开事件
  const handleMouseUp = () => {
    // 结束拖拽和调整大小状态
    isDragging.value = false
    isResizing.value = false
    activeControlPoint.value = null
  }

  // 导出编辑数据（完整数据，包含所有属性和状态）
  const exportEditData = () => {
    // 创建一个深拷贝，避免修改原始数据
    const exportData = JSON.parse(JSON.stringify(canvasElements.value))

    // 生成JSON文件并下载
    downloadJSON(exportData, 'canvas-edit-data.json')
  }

  // 导出展示数据（精简数据，只包含渲染必需的属性）
  const exportDisplayData = () => {
    // 创建精简版的数据
    const displayData = canvasElements.value.map((element) => {
      // 基础属性
      const baseElement = {
        id: element.id,
        type: element.type,
        x: element.x,
        y: element.y,
      }

      // 根据元素类型添加特定属性
      if (element.type === ElementType.TEXT) {
        return {
          ...baseElement,
          text: element.text,
          fontFamily: element.fontFamily,
          fontSize: element.fontSize,
        }
      } else if (element.type === ElementType.IMAGE) {
        return {
          ...baseElement,
          width: element.width,
          height: element.height,
          imageUrl: element.imageUrl,
        }
      } else if (element.type === ElementType.RECTANGLE) {
        return {
          ...baseElement,
          width: element.width,
          height: element.height,
          color: element.color,
        }
      } else if (element.type === ElementType.CIRCLE) {
        return {
          ...baseElement,
          radius: element.radius,
          color: element.color,
        }
      }

      return baseElement
    })

    // 生成JSON文件并下载
    downloadJSON(displayData, 'canvas-display-data.json')
  }

  // 下载JSON文件的辅助函数
  const downloadJSON = (data, filename) => {
    // 将数据转换为JSON字符串
    const jsonString = JSON.stringify(data, null, 2)

    // 创建Blob对象
    const blob = new Blob([jsonString], { type: 'application/json' })

    // 创建下载链接
    const url = URL.createObjectURL(blob)
    const link = document.createElement('a')
    link.href = url
    link.download = filename

    // 触发下载
    document.body.appendChild(link)
    link.click()

    // 清理
    document.body.removeChild(link)
    URL.revokeObjectURL(url)

    // 显示成功消息
    alert(`${filename} 导出成功！`)
  }

  // 导入数据的方法
  const importData = () => {
    fileInput.value.click()
  }
</script>

<style scoped>
  .editor-container {
    display: flex;
    width: 100%;
    height: 100vh;
    overflow: hidden;
  }

  .left-panel {
    width: 200px;
    padding: 15px;
    border-right: 1px solid #ddd;
    background-color: #f5f5f5;
  }

  .center-panel {
    flex: 1;
    display: flex;
    justify-content: center;
    align-items: center;
    background-color: #f9f9f9;
    padding: 20px;
    overflow: auto;
  }

  .right-panel {
    width: 250px;
    padding: 15px;
    border-left: 1px solid #ddd;
    background-color: #f5f5f5;
    overflow-y: auto;
  }

  h3 {
    margin-top: 0;
    margin-bottom: 15px;
    font-size: 16px;
    color: #333;
  }

  .component-list {
    display: flex;
    flex-direction: column;
    gap: 10px;
  }

  .component-item {
    padding: 8px 12px;
    background-color: #fff;
    border: 1px solid #ddd;
    border-radius: 4px;
    cursor: pointer;
    transition: all 0.3s;
  }

  .component-item:hover {
    background-color: #e6f7ff;
    border-color: #1890ff;
  }

  .property-panel {
    display: flex;
    flex-direction: column;
    gap: 12px;
  }

  .property-item {
    display: flex;
    flex-direction: column;
    gap: 5px;
  }

  .property-item label {
    font-size: 14px;
    color: #666;
  }

  .property-item input,
  .property-item select {
    padding: 6px 8px;
    border: 1px solid #ddd;
    border-radius: 4px;
    width: 100%;
  }

  .property-status {
    margin-top: 15px;
    padding: 8px;
    background-color: #f0f9eb;
    color: #67c23a;
    border-radius: 4px;
    text-align: center;
  }

  .no-selection {
    color: #999;
    text-align: center;
    padding: 20px 0;
  }

  canvas {
    border: 1px solid #ddd;
    background-color: white;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
  }

  .export-btn {
    margin-top: 20px;
    background-color: #1890ff;
    color: white;
    font-weight: bold;
  }

  .export-dialog {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0, 0, 0, 0.5);
    display: flex;
    justify-content: center;
    align-items: center;
    z-index: 1000;
  }

  .export-dialog-content {
    background-color: white;
    padding: 20px;
    border-radius: 8px;
    width: 300px;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  }

  .export-options {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin: 20px 0;
  }

  .export-options button {
    padding: 10px;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    transition: all 0.3s;
  }

  #export-edit-data {
    background-color: #1890ff;
    color: white;
  }

  #export-display-data {
    background-color: #52c41a;
    color: white;
  }

  #close-dialog {
    width: 100%;
    padding: 8px;
    background-color: #f5f5f5;
    border: 1px solid #d9d9d9;
    border-radius: 4px;
    cursor: pointer;
  }

  #export-edit-data:hover,
  #export-display-data:hover {
    opacity: 0.8;
  }
</style>
